package com.gaojx.lang.rule;

import cn.hutool.core.io.FileUtil;
import com.gaojx.lang.util.FileAndFolderUtil;
import com.gaojx.lang.util.spring.SpringContextUtil;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.FileCopyUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Path;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.List;

/**
 * @author junxiang.gao
 * @since 2020/8/19
 */
public enum GroovyFactory {

    /**
     * 单例
     */
    INSTANCE;

    private static final Logger LOGGER = LoggerFactory.getLogger(GroovyFactory.class);

    private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();

    public List<IRule> getIRuleFromPackage(String filePath) throws IOException, IllegalAccessException, InstantiationException {
//        URL url = this.getClass().getClassLoader().getResource(filePath);
//        String path = url.getPath();
//        LOGGER.error("url=============>{}", this.getClass().getClassLoader().getResource(filePath));

//        ClassPathResource resource = new ClassPathResource(filePath);
//        File resourceFile = resource.getFile();

        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filePath);

        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

        Resource[] resources = resolver.getResources("classpath:groovy/*.groovy");

        List<String> groovyStrs = new ArrayList<>();


        ApplicationContext applicationContext = SpringContextUtil.getApplicationContext();
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();


        for (Resource resource : resources) {
            InputStream inputStream = resource.getInputStream();
            byte[] bytes = FileCopyUtils.copyToByteArray(inputStream);
            groovyStrs.add(new String(bytes));

            registerBeanToFactory(beanFactory, resource);
        }


        groovyStrs.forEach(System.out::println);


        List<IRule> ruleList = new ArrayList<>();

        for (String groovyStr : groovyStrs) {
            Class<?> clazz = groovyClassLoader.parseClass(groovyStr);
            if (clazz != null) {
                Object instance = clazz.newInstance();
                if (instance != null) {
                    if (instance instanceof IRule) {
                        ruleList.add((IRule) instance);
                    }
                }
            }
        }

        return ruleList;


        //throw new IllegalArgumentException("读取Groovy文件异常");
    }

    private void registerBeanToFactory(DefaultListableBeanFactory beanFactory, Resource resource) throws IOException {

        // 注册的bean名称，如果是同名bean，则覆盖
        String beanName = resource.getFilename().replace(".groovy", "");

        GenericBeanDefinition bd = new GenericBeanDefinition();

        bd.setBeanClassName("org.springframework.scripting.groovy.GroovyScriptFactory");

        bd.setAttribute("org.springframework.scripting.support.ScriptFactoryPostProcessor.refreshCheckDelay",
                5000);

        bd.setAttribute("org.springframework.scripting.support.ScriptFactoryPostProcessor.language",
                "groovy");

        bd.getConstructorArgumentValues().addIndexedArgumentValue(0, resource.getURI().toString());

        beanFactory.registerBeanDefinition(beanName, bd);
    }
}
